print("202510131420")
-- runTag 0-local 1-shopwegame 2-online
local runTag = 2
local singleTradeTimeoutSeconds = 60 -- 单次交易最多等待1分钟
local maxTradeTime = 600             -- 10分钟超时
local waitTradeTime = 600            -- 交易玩家不在线，等待上线时间10分钟
local tradeInterval = 5              -- 交易轮次间隔时间（秒）
local maxTradeRequestTime = 300      -- 最大交易请求等待时间（3分钟，玩家在线但不点同意交易）
local postOrderWaitSeconds = 5      -- 订单完成后再次检查等待时间（秒）

-- 获取库存配置
local OPTIMIZATION_CONFIG = {
    -- 缓存配置
    inventoryCacheDuration = 3,      -- 库存缓存时间（秒）
    -- 批量处理配置
    itemDelay = 0.15,               -- 单个物品延迟
}  

-- 统一状态文件：存储队列、确认记录、服务器状态
local STATE_FILE = "sync_state.json"

-- 不需要删除好友的用户ID列表配置
local EXEMPT_FRIEND_DELETE_USER_IDS = {
    -- 9465257421, -- 测试用户 mayue0827
    -- 8439497583 -- 测试用户 pssmurf0077
}

-- 同步配置
local SYNC_CONFIG = {
    maxRetryInterval = 300, -- 最大重试间隔（5分钟）
    sequenceTimeout = 60,   -- 序列超时时间（秒）
    checkInterval = 10,     -- 检查间隔（秒）
}

-- 统一状态结构
local syncState = {
    queue = {},              -- 待处理队列
    isProcessing = false,    -- 是否正在处理
    lastProcessTime = 0,     -- 上次处理时间
    serverHealthy = true,    -- 服务器健康状态
    consecutiveFailures = 0, -- 连续失败次数
    recoveryMode = false,    -- 恢复模式
    lastRecoveryTime = 0,    -- 上次恢复时间
    activeOrder = nil,       -- 进行中的订单信息（用于故障恢复，最多1个）
    acks_done = {},          -- 订单完成的持久标记：orderMainId -> completedAt 时间戳
    loggedOrders = {},       -- 已打印日志的订单：orderMainId -> logType -> true
}

-- baseUrl 和 authSecret 用于订单查询与回调（硬编码）
local  baseUrl = "https://u7playearn.shopwegame.com/dev-api/play-earn/api/order"
if runTag == 1 then
    baseUrl = "https://player2earn.shopwegame.com/dev-api/play-earn/api/order"
elseif runTag == 2 then
    baseUrl = "https://player2earn.com/prod-api/play-earn/api/order"
end
local  authSecret = "8f9dbe334ca364eac2b18ca437fde25d"
local  lokiUrl = "https://lokipush.shopwegame.com/loki/api/v1/push"
-- 服务获取
local LocalPlayerName = game.Players.LocalPlayer.Name                                         -- 当前玩家名
local HttpService = game:GetService("HttpService")                                            -- 用于 HTTP 请求
local ReplicatedStorage = game:GetService("ReplicatedStorage")  -- 获取库存相关
local Trade = ReplicatedStorage:WaitForChild("Trade") -- 交易相关
local GetFullInventory = game:GetService("ReplicatedStorage").Remotes.Extras.GetFullInventory -- 获取库存
local Players = game:GetService("Players")                                                    -- 玩家列表
local game_id = game.PlaceId * 3                                                              -- 交易接受参数使用

-- 全局变量存储 UpdateTrade 事件的最新数据
local latestTradeData = nil

math.randomseed(os.time())

-- 监听 UpdateTrade 事件，存储最新的交易数据作为兜底
Trade:WaitForChild("UpdateTrade").OnClientEvent:Connect(function(data)
    latestTradeData = data
    log("UpdateTrade 事件捕获，更新兜底数据: " .. HttpService:JSONEncode(data))
end)

-- 说话功能：将日志 JSON 中的 message 字段作为聊天内容发送
local TextChatService = game:GetService("TextChatService")

local function getGeneralChannel()
    local ok, channel = pcall(function()
        if TextChatService.ChatVersion == Enum.ChatVersion.TextChatService then
            local channels = TextChatService:FindFirstChild("TextChannels")
            return channels and channels:FindFirstChild("RBXGeneral")
        end
        return nil
    end)
    if ok then return channel end
end

local function say(message)
    if type(message) ~= "string" or message == "" then return end
    -- 新版 TextChat（仅在开启新聊天系统时可用）
    local channel = getGeneralChannel()
    if channel then
        pcall(function()
            channel:SendAsync(string.sub(message, 1, 200))
        end)
    end
end

-- 给客服发送消息的API接口
local function sendCustomerServiceMessages(hintType)
    -- 构建URL，添加客服号标识 发送消息类型
    local url = string.format("%s/customer-service?authSecret=%s&robloxUserName=%s&type=messages&hintType=%s", 
                             baseUrl, authSecret, LocalPlayerName,hintType)
    
    local success, response = pcall(function()
        local result = httpGet(url)
        if not result then
            return nil, "HTTP request failed"
        end
        
        local result_d = HttpService:JSONDecode(result)
        if result_d.code == 200 then
            return result_d.data
        else
            return nil, "API returned error code: " .. tostring(result_d.code)
        end
    end)
    
    if not success then
        log("sendCustomerServiceMessages 请求失败: " .. tostring(response))
        return nil
    end
    
    return response
end
-- 交易提示消息（仅在指定的5个位置发送）
local function sendTradeHint(hintType)
    if hintType == 1 then
        -- say("请接受交易申请进行交易")
        say("Plz accept the trade request.")
    elseif hintType == 2 or hintType == 3 then
        -- say("请放置正确的物品进行交易")
        say("Plz put the correct items to trade")
    elseif hintType == 4 then
        -- say("请接受交易申请进行交易")
        say("Plz accept the trade request.")
    elseif hintType == 5 then
        -- say("交易失败，请再次在网站提交售卖请求")
        say("Trade failed, plz quit the server and sumbit the trading request in site again.")
    elseif hintType == 6 then
        -- say("收货开始交易")
        say("Trading start, plz accept the trading request and submit correct items.")
    elseif hintType == 7 then
        -- say("发货开始交易")
        say("Trading start, plz accept the trading request.")
    end
    -- sendCustomerServiceMessages(hintType)
end

-- 只上传这些类型的日志到 Loki（交易/订单相关）
local uploadLogTypes = {
    trade = true,
    trade_start = true,
    trade_success = true,
    trade_error = true,
    order_query = true,
    order_sync = true,
    progress = true,
    delete_friend = true
}

-- 安全的文件写入函数
-- mode: "append" 追加模式, "overwrite" 覆盖模式, 默认追加模式
local function safeWriteFile(filename, content, mode)
    mode = mode or "append"

    if mode == "append" then
        local success, err = pcall(function()
            appendfile(filename, content)
        end)

        if not success then
            local writeSuccess, writeErr = pcall(function()
                writefile(filename, content)
            end)

            if not writeSuccess then
                print("文件写入失败: " .. filename .. " - " .. tostring(writeErr))
            end
        end
    else -- overwrite mode
        local success, err = pcall(function()
            writefile(filename, content)
        end)

        if not success then
            local appendSuccess, appendErr = pcall(function()
                appendfile(filename, content)
            end)

            if not appendSuccess then
                print("文件写入失败: " .. filename .. " - " .. tostring(appendErr))
            end
        end
    end
end

-- 增强的日志上传函数（HttpGet 版本）
local function uploadToLoki(logMessage, metadata)
    -- metadata 可以包含: orderMainId, username, orderStatus, log_type 等

    -- 使用 Loki 标准格式
    local success, err = pcall(function()
        -- 获取当前时间戳（纳秒级）
        local timestamp = os.time() * 1000000000

        -- 构建 Loki 标准数据
        local lokiData = {
            streams = {
                {
                    stream = {
                        app = "roblox_mm2",
                        log_type = metadata and metadata.log_type or "general",
                        username = metadata and metadata.username or LocalPlayerName,
                        orderMainId = metadata and metadata.orderMainId and tostring(metadata.orderMainId) or nil,
                        deliveryOrderId = metadata and metadata.deliveryOrderId and tostring(metadata.deliveryOrderId) or nil,
                        orderStatus = metadata and metadata.orderStatus and tostring(metadata.orderStatus) or nil,
                        makeStatus = metadata and metadata.makeStatus and tostring(metadata.makeStatus) or nil
                    },
                    values = {
                        { tostring(timestamp), logMessage }
                    }
                }
            }
        }

        -- 清理为 nil 的标签键
        for k, v in pairs(lokiData.streams[1].stream) do
            if v == nil then
                lokiData.streams[1].stream[k] = nil
            end
        end

        local response = request({
            Url = lokiUrl,
            Method = "POST",
            Headers = {
                ["Content-Type"] = "application/json"
            },
            Body = HttpService:JSONEncode(lokiData)
        })

        if response.Success then
            -- print("请求成功:", response.Body)
        else
            log(HttpService:JSONEncode({
                message = "上传日志请求失败",
                response = response,
            }))
        end
        return response
    end)

    if success then
        return -- Loki 标准格式上传成功，返回
    end
end

-- 日志函数优化
local log = function(s, metadata) -- 日志
    -- log(s, metadata): 记录到 log.txt；仅交易相关类型才上传到 Loki
    local logMessage = string.format("[%s] %s", os.date("%Y-%m-%d %H:%M:%S"), tostring(s))

    -- 记录到本地文件
    local success, err = pcall(function()
        appendfile("log.txt", logMessage .. "\n")
    end)
    if not success then
        writefile("log.txt", logMessage .. "\n")
    end

    -- 若可从 JSON 提取 message，则尝试说话
    -- do
    --     local ok, parsed = pcall(function()
    --         if type(s) == "string" then
    --             return HttpService:JSONDecode(s)
    --         end
    --         return nil
    --     end)
    --     if ok and type(parsed) == "table" and type(parsed.message) == "string" then
    --         say(parsed.message)
    --     end
    -- end

    -- 仅上传白名单内的交易日志
    if runTag ~= 0 and type(metadata) == "table" then
        local lt = metadata.log_type
        if lt and uploadLogTypes[lt] then
            uploadToLoki(tostring(s), metadata)
        end
    end
end

-- HTTP请求函数优化
local function httpGet(url)
    -- httpGet(url): 封装 game:HttpGet，失败记录日志。
    local success, result = pcall(function()
        return game:HttpGet(url, true)
    end)
    if success then
        return result
    else
        log("url请求失败：" .. url)
        return nil
    end
end

-- 将 totalDelivered 转换为发货订单的 items 结构
local function buildDeliveryItemsFromTotalDelivered(totalDelivered, orderStatus, receiveStatus)
    local items = {}
    for itemId, data in pairs(totalDelivered) do
        table.insert(items, {
            orderDeliverQuantity = data.quantity,  -- 实际发货数量
            tradeId = itemId,                      -- 物品ID
            deliveryOrderItemId = data.deliveryOrderItemId  -- 发货订单物品ID
        })
    end
    return items
end

-- 将 totalReceived 转换为服务器需要的 orderList 结构
local function buildOrderListFromTotalReceived(totalMap, orderStatus, receiveStatus)
    -- 输出为扁平结构：{ orderId, orderStatus, receiveStatus?, orderProductId?, quantity? }
    local list = {}
    if type(totalMap) ~= "table" then return list end
    for _, item in pairs(totalMap) do
        local entry = { orderId = item.orderId, orderStatus = orderStatus or 0 }
        -- 不用传receiveStatus
        -- if receiveStatus ~= nil then entry.receiveStatus = receiveStatus end
        if item.orderProductId ~= nil then entry.orderProductId = item.orderProductId end
        local q = tonumber(item.quantity)
        if q and q > 0 then 
            entry.quantity = q 
            table.insert(list, entry)
        end
       
    end
    return list
end


local function jump()
    local keys = { 0x20, 0x20, 0x20, 0x20, 0x41, 0x44, 0x53, 0x57 }
    local randomKey = keys[math.random(1, #keys)]
    pcall(function()
        keypress(randomKey)
        task.wait(0.2)
        keyrelease(randomKey)
    end)
end

task.spawn(function()
    -- jump(): 每 60 秒随机按键一次，保持角色活跃。
    while task.wait(60) do
        jump()
    end
end)

-- 删除好友接口
local function deleteFriend(robloxUserId)
    if not robloxUserId then
        log("deleteFriend 错误：缺少 robloxUserId 参数")
        return false
    end
    
    local url = string.format("http://45.77.227.112:8817/api/roblox/friends/del?delId=%s&userName=%s", tostring(robloxUserId), LocalPlayerName)
    local success, response = pcall(function()
        local result = httpGet(url)
        if not result then
            return nil, "HTTP request failed"
        end

        local result_d = HttpService:JSONDecode(result)
        if result_d.code == 200 then
            local data = result_d.data
            local logData = {
                message = "删除好友成功",
                robloxUserId = robloxUserId,
                data = data
            }
            log(HttpService:JSONEncode(logData), {
                log_type = "delete_friend",
                robloxUserId = robloxUserId,
                user = result_d.message,
            })
            return data -- 删除好友成功
        else
            return nil, "删除好友失败: " .. tostring(result_d.code)
        end
    end)

    if not success then
        log("deleteFriend 请求失败: " .. tostring(response))
        return false
    end

    if type(response) == "table" then
        return true
    else
        return false
    end
end

-- 监听玩家加入事件
-- game.Players.PlayerAdded:Connect(function(player)
--     -- 跳过自己
--     if player == game.Players.LocalPlayer then return end
    
--     -- 检查是否是好友
--     local isFriend = game.Players.LocalPlayer:IsFriendsWith(player.UserId)
--     if not isFriend then
--         -- 检查是否在豁免列表中
--         local shouldKick = true
--         for _, exemptId in ipairs(EXEMPT_FRIEND_DELETE_USER_IDS) do
--             if player.UserId == exemptId then
--                 shouldKick = false
--                 break
--             end
--         end
        
--         if shouldKick then
--             -- 先删除好友关系
--             deleteFriend(player.UserId)
--             -- 然后踢出房间
--             log(HttpService:JSONEncode({
--                 message = "非好友玩家被踢出房间",
--                 playerName = player.Name,
--                 playerId = player.UserId
--             }))
--         end
--     end
-- end)

-- 检查是否已打印过特定类型的日志
local function hasLoggedOrder(orderMainId, logType)
    if not syncState.loggedOrders[orderMainId] then
        return false
    end
    return syncState.loggedOrders[orderMainId][logType] == true
end

-- 标记订单日志已打印
local function markOrderLogged(orderMainId, logType)
    if not syncState.loggedOrders[orderMainId] then
        syncState.loggedOrders[orderMainId] = {}
    end
    syncState.loggedOrders[orderMainId][logType] = true
end

-- 收货订单获取
local function getReceivingOrder()
    if runTag == 0 then
        return {
            orderMainId = "1960614033613475841",                    -- 主订单ID
            robloxUserName = "pssmurf0077",                         -- 卖家roblox用户名
            robloxUserId = 8439497583,                              -- 卖家roblox用户id
            inventoryAccountName = "pssmurf0078",                   -- 库存号roblox用户名
            orderList = {                                           -- 订单列表
                {
                    orderId = "1960614033747693560",                -- 订单ID
                    product = {
                        tradeId = "Saw",                            -- 物品ID
                        orderProductId = "1960614033936437251",     -- 订单物品ID
                        quantity = 1                                -- 物品数量
                    }
                },
                -- {
                --     orderId = "1960614033747693561",                -- 订单ID
                --     product = {
                --         tradeId = "Tree",                           -- 物品ID
                --         orderProductId = "1960614033936437252",     -- 订单物品ID
                --         quantity = 1                                -- 物品数量
                --     }
                -- },
                -- {
                --     orderId = "1960614033747693562",                -- 订单ID
                --     product = {
                --         tradeId = "Bats",                           -- 物品ID
                --         orderProductId = "1960614033936437253",     -- 订单物品ID
                --         quantity = 1                                -- 物品数量
                --     }
                -- },
                -- {
                --     orderId = "1960614033747693563",                -- 订单ID
                --     product = {
                --         tradeId = "Frostfade_K_2023",                           -- 物品ID
                --         orderProductId = "1960614033936437254",     -- 订单物品ID
                --         quantity = 1                                -- 物品数量
                --     }
                -- },
                -- {
                --     orderId = "1960614033747693564",                -- 订单ID
                --     product = {
                --         tradeId = "DeepSea",                           -- 物品ID
                --         orderProductId = "1960614033936437255",     -- 订单物品ID
                --         quantity = 1                                -- 物品数量
                --     }
                -- }
            }
        }
    end

    local url = string.format("%s/query?authSecret=%s&robloxUserName=%s", baseUrl, authSecret, LocalPlayerName)
    local success, response = pcall(function()
        local result = httpGet(url)
        if not result then
            return nil, "HTTP request failed"
        end

        local result_d = HttpService:JSONDecode(result)
        if result_d.code == 200 then
            local data = result_d.data
            local logData = {
                message = "收货订单查询",
                data = data
            }
            log(HttpService:JSONEncode(logData), {
                log_type = "order_query",
                orderMainId = data.orderMainId,
            })
            
            -- 强化去重逻辑：多重检查机制
            if data.orderMainId then
                local orderMainId = tostring(data.orderMainId)
                
                -- 1. 检查 acks_done（持久完成标记）
                if type(syncState) == "table" and syncState.acks_done and syncState.acks_done[orderMainId] then
                    local doneAt = syncState.acks_done[orderMainId]
                    -- 只打印一次日志
                    if not hasLoggedOrder(orderMainId, "acks_done") then
                        log(HttpService:JSONEncode({
                            message = "订单已完成(acks_done)，忽略返回",
                            orderMainId = data.orderMainId,
                            doneAt = doneAt,
                            timeSinceDone = os.time() - doneAt
                        }))
                        markOrderLogged(orderMainId, "acks_done")
                    end
                    return nil, "order already done by ack"
                end
                
                -- 2. 检查 activeOrder（进行中的订单）
                if type(syncState) == "table" and syncState.activeOrder and 
                   syncState.activeOrder.orderMainId == data.orderMainId then
                    -- 只打印一次日志
                    if not hasLoggedOrder(orderMainId, "activeOrder") then
                        log(HttpService:JSONEncode({
                            message = "订单正在进行中(activeOrder)，忽略返回",
                            orderMainId = data.orderMainId,
                            activeOrderStatus = syncState.activeOrder.orderStatus,
                            lastUpdateTime = syncState.activeOrder.lastUpdateTime
                        }))
                        markOrderLogged(orderMainId, "activeOrder")
                    end
                    return nil, "order already active"
                end
                
                -- 3. 检查队列中是否有相同订单的完成状态
                if type(syncState) == "table" and syncState.queue then
                    for _, task in ipairs(syncState.queue) do
                        if task.data and task.data.orderMainId == data.orderMainId and 
                           task.data.orderStatus == 4 then
                            -- 只打印一次日志
                            if not hasLoggedOrder(orderMainId, "queue_completed") then
                                log(HttpService:JSONEncode({
                                    message = "订单已在队列中完成，忽略返回",
                                    orderMainId = data.orderMainId,
                                    taskId = task.id,
                                    orderStatus = task.data.orderStatus,
                                    receiveStatus = task.data.receiveStatus
                                }))
                                markOrderLogged(orderMainId, "queue_completed")
                            end
                            return nil, "order already completed in queue"
                        end
                    end
                end
            end
            return data -- 直接返回完整的主订单数据
        else
            return nil, "API returned error code: " .. tostring(result_d.code)
        end
    end)

    if not success then
        log("getReceivingOrder 请求失败: " .. tostring(response))
        return {}
    end

    if type(response) == "table" then
        return response
    else
        return {}
    end
end

-- 发货订单获取优化 - 支持多物品
local function getDeliveryOrder()
    if runTag == 0 then
        return {
            deliveryOrderId = "1976918433051009025",           -- 发货订单ID
            robloxUserName = "pssmurf0077",                     -- 买家roblox用户名
            robloxUserId = 8439497583,                          -- 买家roblox用户id
            createTime = 1760169058466,                          -- 创建时间
            items = {                                           -- 物品列表
                {
                    deliveryOrderItemId = "1976918433084563457", -- 发货订单物品ID
                    tradeId = "Saw",                            -- 物品ID
                    orderQuantity = 2                           -- 物品数量
                }
            }
        }
    end

    local url = string.format("%s/queryDeliveryOrder?authSecret=%s&robloxUserName=%s", baseUrl, authSecret, LocalPlayerName)
    local success, response = pcall(function()
        local result = httpGet(url)
        if not result then
            return nil, "HTTP request failed"
        end

        local result_d = HttpService:JSONDecode(result)
        if result_d.code == 200 then
            local data = result_d.data
            local logData = {
                message = "发货订单查询",
                data = data
            }
            log(HttpService:JSONEncode(logData), {
                log_type = "order_query",
                deliveryOrderId = data.deliveryOrderId,
            })
            
            -- 强化去重逻辑：多重检查机制
            if data.deliveryOrderId then
                local deliveryOrderId = tostring(data.deliveryOrderId)
                
                -- 1. 检查 acks_done（持久完成标记）
                if type(syncState) == "table" and syncState.acks_done and syncState.acks_done[deliveryOrderId] then
                    local doneAt = syncState.acks_done[deliveryOrderId]
                    log(HttpService:JSONEncode({
                        message = "订单已完成(acks_done)，忽略返回",
                        deliveryOrderId = data.deliveryOrderId,
                        doneAt = doneAt,
                        timeSinceDone = os.time() - doneAt
                    }))
                    return nil, "order already done by ack"
                end
                
                -- 2. 检查 activeOrder（进行中的订单）
                if type(syncState) == "table" and syncState.activeOrder and 
                   syncState.activeOrder.deliveryOrderId == data.deliveryOrderId then
                    log(HttpService:JSONEncode({
                        message = "订单正在进行中(activeOrder)，忽略返回",
                        deliveryOrderId = data.deliveryOrderId,
                        activeOrderStatus = syncState.activeOrder.makeStatus,
                        lastUpdateTime = syncState.activeOrder.lastUpdateTime
                    }))
                    return nil, "order already active"
                end
                
                -- 3. 检查队列中是否有相同订单的完成状态
                if type(syncState) == "table" and syncState.queue then
                    for _, task in ipairs(syncState.queue) do
                        if task.data and task.data.deliveryOrderId == data.deliveryOrderId and 
                           task.data.makeStatus == 2 then
                            log(HttpService:JSONEncode({
                                message = "订单已在队列中完成，忽略返回",
                                deliveryOrderId = data.deliveryOrderId,
                                taskId = task.id,
                                makeStatus = task.data.makeStatus,
                                receiveStatus = task.data.receiveStatus
                            }))
                            return nil, "order already completed in queue"
                        end
                    end
                end
            end
            return data -- 直接返回完整的主订单数据
        else
            return nil, "API returned error code: " .. tostring(result_d.code)
        end
    end)

    if not success then
        log("getDeliveryOrder 请求失败: " .. tostring(response))
        return {}
    end

    if type(response) == "table" then
        return response
    else
        return {}
    end
end

-- 检查玩家是否在线且在同一房间，并且已经加载完成
local function isUserOnlineAndReady(user)
    local p = Players:FindFirstChild(user)
    if not p then
        return false, "玩家不在线"
    end

    -- 检查玩家是否在同一服务器/房间
    if not p.Parent then
        return false, "玩家不在当前房间"
    end

    -- 检查玩家是否已经加载完成（有Character）
    if not p.Character then
        return false, "玩家角色未加载完成"
    end

    -- 检查玩家角色是否有必要的组件（确保完全加载）
    local character = p.Character
    if not character:FindFirstChild("Humanoid") then
        return false, "玩家角色Humanoid未加载"
    end

    if not character:FindFirstChild("HumanoidRootPart") then
        return false, "玩家角色HumanoidRootPart未加载"
    end

    -- 检查玩家是否在有效位置（避免在加载中或异常状态）
    local humanoidRootPart = character.HumanoidRootPart
    if not humanoidRootPart or not humanoidRootPart.Position then
        return false, "玩家位置信息无效"
    end

    return true, "玩家在线且已准备就绪"
end

-- 检查玩家是否在线且在同一房间（简化版本，用于快速检查）
local function isUserInSameRoom(user)
    local p = Players:FindFirstChild(user)
    if not p then
        return false, "玩家不在线"
    end

    -- 检查玩家是否在同一服务器/房间
    if not p.Parent then
        return false, "玩家不在当前房间"
    end

    return true, "玩家在同一房间"
end

-- 等待玩家完全加载完成（带超时）
local function waitForUserReady(user, maxWaitSeconds)
    maxWaitSeconds = maxWaitSeconds or 30
    local deadline = os.time() + maxWaitSeconds

    while os.time() < deadline do
        local isReady, reason = isUserOnlineAndReady(user)
        if isReady then
            return true, "玩家已准备就绪"
        end

        -- 每2秒检查一次
        task.wait(2)
    end

    return false, "等待玩家加载超时"
end

-- 给指定在线玩家发起交易
local function sendTradeRequest(user)
    local p = Players:FindFirstChild(user)
    if p then
        -- 在发起交易前检查玩家是否已准备就绪
        local isReady, reason = isUserOnlineAndReady(user)
        if not isReady then
            log(HttpService:JSONEncode({
                message = "无法发起交易，玩家未准备就绪: " .. reason,
                user = user,
                reason = reason
            }))
            return false
        end

        local args = { [1] = p }
        Trade.SendRequest:InvokeServer(unpack(args))
        return true
    end
    return false
end

-- 动态获取 Trade 对象，如果为 nil 则重新获取
local function getTradeObject()
    local rs = game:GetService("ReplicatedStorage")
    if not rs or not rs:FindFirstChild("Trade") then
        return nil
    end
    return rs:FindFirstChild("Trade")
end

local function getCurTradeStatus()
    -- 动态获取 Trade 对象
    local tradeObj = getTradeObject()
    if not tradeObj or not tradeObj.GetTradeStatus then
        log("警告: Trade 对象或 GetTradeStatus 不存在，尝试重新获取")
        -- 尝试强制等待一次
        task.wait(1)
        tradeObj = getTradeObject()
        if not tradeObj or not tradeObj.GetTradeStatus then
            log("警告: 重新获取 Trade 对象失败")
            return "None", nil
        end
    end

    -- 使用 pcall 保护，防止 Trade 为 nil 时报错
    local success, curTradeStatus, tradeData = pcall(function()
        return tradeObj.GetTradeStatus:InvokeServer()
    end)

    if not success then
        log("警告: getCurTradeStatus 调用失败: " .. tostring(curTradeStatus))
        return "None", nil
    end

    -- 安全 JSON 编码日志（防止 nil 或不可编码导致错误）
    local okEnc, enc = pcall(function() return HttpService:JSONEncode(tradeData) end)
    if okEnc then
        log(string.format("交易状态: %s", tostring(curTradeStatus)))
        log(string.format("交易数据: %s", enc))
    else
        log(string.format("交易状态: %s", tostring(curTradeStatus)))
        log("交易数据: <无法 JSONEncode 的值>, type=" .. tostring(type(tradeData)))
    end

    -- 规范化不同版本返回结构：
    -- 有些版本返回 { Receiver=..., Sender=..., LastOffer=... }
    -- 我们把其转换为兼容的 { Player1 = Sender, Player2 = Receiver, LastOffer = ... }
    if type(tradeData) == "table" and (tradeData.Receiver ~= nil or tradeData.Sender ~= nil) then
        local norm = {}
        norm.Player1 = tradeData.Sender or {}
        norm.Player2 = tradeData.Receiver or {}
        -- 保留 LastOffer（不同大小写兼容）
        norm.LastOffer = tradeData.LastOffer or tradeData.lastOffer or tradeData.LastOffer
        tradeData = norm
        -- 重新记录归一化后的 tradeData（安全编码）
        local ok2, enc2 = pcall(function() return HttpService:JSONEncode(tradeData) end)
        if ok2 then
            log("已归一化交易数据: " .. enc2)
        else
            log("已归一化交易数据，无法 JSONEncode")
        end
    end

    -- 如果 tradeData 是空表或所有字段均为 nil，则视为无效，使用兜底数据
    if type(tradeData) == "table" then
        local hasNonNil = false
        for k, v in pairs(tradeData) do
            if v ~= nil then
                hasNonNil = true
                break
            end
        end
        if not hasNonNil or (next(tradeData) == nil) then
            if latestTradeData then
                local ok3, enc3 = pcall(function() return HttpService:JSONEncode(latestTradeData) end)
                log("使用 UpdateTrade 兜底数据: " .. (ok3 and enc3 or "<无法 JSONEncode 兜底数据>"))
                tradeData = latestTradeData
            else
                log("警告: tradeData 为空且无 UpdateTrade 兜底数据")
                tradeData = nil
            end
        end
    elseif not tradeData and latestTradeData then
        local ok3, enc3 = pcall(function() return HttpService:JSONEncode(latestTradeData) end)
        log("使用 UpdateTrade 兜底数据: " .. (ok3 and enc3 or "<无法 JSONEncode 兜底数据>"))
        tradeData = latestTradeData
    end

    return curTradeStatus, tradeData
end

-- 使用服务器提供的 SetRequestsEnabled 来彻底关闭他人交易请求
local function setTradeRequestsEnabled(enabled)
    local RS = game:GetService("ReplicatedStorage")
    local tradeFolder = RS:FindFirstChild("Trade")
    if not tradeFolder then return false, "Trade folder not found" end
    local setter = tradeFolder:FindFirstChild("SetRequestsEnabled")
    if not setter then return false, "SetRequestsEnabled not found" end
    if setter:IsA("RemoteEvent") then
        local ok, err = pcall(function()
            setter:FireServer(enabled and true or false)
        end)
        if ok then
            -- log(HttpService:JSONEncode({ message = "SetRequestsEnabled success", enabled = enabled }))
            return true
        else
            -- log(HttpService:JSONEncode({ message = "SetRequestsEnabled failed", error = tostring(err) }))
            return false, err
        end
    elseif setter:IsA("RemoteFunction") then
        local ok, res = pcall(function()
            return setter:InvokeServer(enabled and true or false)
        end)
        if ok then
            log(HttpService:JSONEncode({ message = "SetRequestsEnabled invoke success", enabled = enabled, result = res }))
            return true
        else
            log(HttpService:JSONEncode({ message = "SetRequestsEnabled invoke failed", error = tostring(res) }))
            return false, res
        end
    end
    return false, "Unsupported SetRequestsEnabled type"
end

-- 开局、重生以及定期应用：强制关闭他人交易请求
task.spawn(function()
    -- 初次
    task.wait(1)
    setTradeRequestsEnabled(false)
    task.wait(0.5)
    pcall(function() updateTradeRequestsUI(false) end)

    -- 重生后再次设置
    local lp = game.Players.LocalPlayer
    if lp then
        lp.CharacterAdded:Connect(function()
            task.wait(1)
            setTradeRequestsEnabled(false)
            task.wait(0.5)
            pcall(function() updateTradeRequestsUI(false) end)
        end)
    end
end)

-- UI 同步：把界面上的 Trade Requests 显示成 OFF/ON
function updateTradeRequestsUI(enabled)
    local pg = game.Players.LocalPlayer:FindFirstChild("PlayerGui")
    if not pg then return end

    local function contains(str, sub)
        return type(str)=="string" and string.find(string.lower(str), string.lower(sub), 1, true) ~= nil
    end

    -- 专用适配：MainGUI.Game.Leaderboard.Container.ToggleRequests.{On,Off}
    local ok = pcall(function()
        local mainGUI = pg:FindFirstChild("MainGUI")
        if mainGUI then
            local gameNode = mainGUI:FindFirstChild("Game")
            local leaderboard = gameNode and gameNode:FindFirstChild("Leaderboard")
            local container = leaderboard and leaderboard:FindFirstChild("Container")
            local toggle = container and container:FindFirstChild("ToggleRequests")
            if toggle then
                local onBtn = toggle:FindFirstChild("On")
                local offBtn = toggle:FindFirstChild("Off")
                if onBtn and offBtn then
                    if enabled then
                        onBtn.Visible = true
                        offBtn.Visible = false
                    else
                        onBtn.Visible = false
                        offBtn.Visible = true
                    end
                    return
                end
            end
        end
    end)

    if ok then return end
end

-- 探测一次 Trade.GetTradeStatus 是否可调用
local function canCallTradeStatusOnce()
    if not Trade or not Trade.GetTradeStatus then return false end
    local ok = pcall(function()
        return Trade.GetTradeStatus:InvokeServer()
    end)
    return ok
end

-- 等待 Trade.GetTradeStatus 可调用（带超时）
local function waitTradeStatusReady(maxWaitSeconds)
    maxWaitSeconds = maxWaitSeconds or 15
    local deadline = os.time() + maxWaitSeconds

    -- 先快速检查一次，如果可用直接返回
    if canCallTradeStatusOnce() then
        return true
    end

    -- 如果不可用，等待并重试
    while os.time() < deadline do
        task.wait(2) -- 增加等待间隔，减少频繁检查
        if canCallTradeStatusOnce() then
            return true
        end
    end
    return false
end

-- 批量获取当前库存（Owned 表）
local function getInventorySnapshot()
    local success, result = pcall(function()
        local inventory = GetFullInventory:InvokeServer(LocalPlayerName)
        if inventory and inventory.Weapons and inventory.Weapons.Owned and type(inventory.Weapons.Owned) == "table" then
            return inventory.Weapons.Owned
        end
        return nil
    end)
    
    if success and type(result) == "table" then
        return result, true
    end
    
    log("库存获取失败，返回空表")
    return {}, false
end

-- 从快照读取某个物品数量
local function getItemNumFromSnapshot(invSnapshot, itemId)
    if type(invSnapshot) ~= "table" then return 0 end
    return invSnapshot[itemId] or 0
end

-- 保留简化读取接口（单次直接拉取，不建议在循环中使用）
local function getItemNum(itemId)
    -- getInventorySnapshot() 返回两个值（库存表, 是否成功）
    -- select(1, getInventorySnapshot()) 的作用是只取第一个返回值（库存表）
    local inv = select(1, getInventorySnapshot())
    return getItemNumFromSnapshot(inv, itemId)
end

-- 优化物品放入交易框函数（限制每批最多4种不同物品）
local function addItemsToTradeOptimized(itemsToOffer)
    local MAX_TRADE_SLOTS = 4  -- 交易栏最多4种不同物品
    local ITEM_DELAY = OPTIMIZATION_CONFIG.itemDelay
    
    -- 限制每批最多4种不同物品（每种物品只占一个位置）
    local limitedItems = {}
    local itemCount = 0
    
    for _, item in ipairs(itemsToOffer) do
        if itemCount < MAX_TRADE_SLOTS then
            table.insert(limitedItems, item)
            itemCount = itemCount + 1
        else
            -- 超过4种物品，停止添加
            break
        end
    end
    
    -- 本轮物品放入交易框
    for _, item in ipairs(limitedItems) do
        for k = 1, item.quantity do
            local itemArgs = { [1] = item.itemId, [2] = "Weapons" }
            Trade.OfferItem:FireServer(unpack(itemArgs))
            task.wait(ITEM_DELAY)
        end
    end
    
    return limitedItems  -- 返回实际放入的物品，用于后续处理
end

-- 统一：单轮1分钟结束后，若仍在发送请求，则取消本次请求
local function cancelPendingTradeRequest(prefix, orderMainId, user)
    local status, _ = getCurTradeStatus()
    if status == "SendingRequest" then
        Trade.CancelRequest:FireServer()
        task.wait(1)
        log(HttpService:JSONEncode({
            message = prefix .. "：单轮1分钟未同意，取消当前交易请求",
            orderMainId = orderMainId,
            user = user
        }))
        -- 提示1：卖家未接受
        sendTradeHint(1)
        return true
    end
    return false
end

-- ================= 保证送达：本地持久化队列 =================
-- 只使用一个文件存储所有状态，减少IO操作
-- 主要功能：请求入队、自动重试、指数退避、有序同步

-- 安全读取文件内容
local function safeRead(path)
    local ok, res = pcall(function() return readfile(path) end)
    if ok and res and #res > 0 then return res end
    return ""
end

-- 加载统一状态
local function loadState()
    local s = safeRead(STATE_FILE)
    if s == "" then return syncState end
    local ok, t = pcall(function() return HttpService:JSONDecode(s) end)
    return ok and t or syncState
end

-- 保存统一状态
local function saveState()
    safeWriteFile(STATE_FILE, HttpService:JSONEncode(syncState), "overwrite")
end

-- 检查服务器健康状态
local function checkServerHealth()
    local testUrl = string.format("%s/query?authSecret=%s&robloxUserName=%s", baseUrl, authSecret, LocalPlayerName)
    local result = httpGet(testUrl)
    return result ~= nil
end

-- 更新服务器健康状态
local function updateServerHealth(isHealthy)
    local now = os.time()

    if isHealthy then
        if not syncState.serverHealthy then
            -- 服务器从故障状态恢复
            syncState.lastRecoveryTime = now
            syncState.recoveryMode = true
            log(HttpService:JSONEncode({
                message = "服务器恢复，进入快速同步模式",
                recoveryTime = now,
                consecutiveFailures = syncState.consecutiveFailures
            }))
        end
        syncState.consecutiveFailures = 0
    else
        syncState.consecutiveFailures = syncState.consecutiveFailures + 1
        if syncState.serverHealthy then
            log(HttpService:JSONEncode({
                message = "服务器故障，进入重试模式",
                consecutiveFailures = syncState.consecutiveFailures
            }))
        end
    end

    syncState.serverHealthy = isHealthy

    -- 如果恢复模式超过10分钟，退出恢复模式
    if syncState.recoveryMode and (now - syncState.lastRecoveryTime) > 600 then
        syncState.recoveryMode = false
        log(HttpService:JSONEncode({
            message = "退出快速同步模式，恢复正常处理间隔"
        }))
    end
end

-- 检查是否可以开始下一个同步
local function canStartNextSync()
    local now = os.time()

    -- 检查序列超时 - 优先检查，避免长时间阻塞
    if syncState.lastProcessTime > 0 and (now - syncState.lastProcessTime) > SYNC_CONFIG.sequenceTimeout then
        log(HttpService:JSONEncode({
            message = "序列超时，重置处理状态",
            lastProcessTime = syncState.lastProcessTime,
            timeout = SYNC_CONFIG.sequenceTimeout,
            isProcessing = syncState.isProcessing
        }))
        syncState.isProcessing = false
    end

    -- 如果正在处理，不能开始新的同步
    if syncState.isProcessing then
        return false
    end

    -- 如果服务器不健康，不能开始同步
    if not syncState.serverHealthy then
        return false
    end

    return true
end

-- 计算重试间隔
local function getRetryInterval(retryCount)
    local base = math.min(SYNC_CONFIG.maxRetryInterval, 2 ^ math.min(retryCount or 0, 6))

    -- 如果服务器健康，使用较短的重试间隔
    if syncState.serverHealthy then
        base = math.min(base, 5) -- 健康时最多5秒
    end

    -- 如果处于恢复模式，使用更短的重试间隔
    if syncState.recoveryMode then
        base = math.min(base, 2) -- 恢复模式最多2秒
    end

    return math.max(1, base)
end

-- 处理队列中的待发送请求
local function flushQueue()
    if runTag == 0 then
        return
    end
    local now = os.time()

    -- 检查服务器健康状态
    local isServerHealthy = checkServerHealth()
    updateServerHealth(isServerHealthy)

    -- 如果没有待处理任务，直接返回
    if #syncState.queue == 0 then
        return
    end
    
    if not canStartNextSync() then
        log(HttpService:JSONEncode({
            message = "无法开始同步",
            queueSize = #syncState.queue,
            isProcessing = syncState.isProcessing,
            serverHealthy = syncState.serverHealthy,
            lastProcessTime = syncState.lastProcessTime,
            timeSinceLastProcess = now - syncState.lastProcessTime
        }))
        return
    end

    -- 按创建时间排序，确保有序同步
    table.sort(syncState.queue, function(a, b)
        return (a.createdAt or 0) < (b.createdAt or 0)
    end)

    -- 处理第一个任务（最旧的）
    local task = syncState.queue[1]
    syncState.isProcessing = true
    syncState.lastProcessTime = now
    
    -- 使用 pcall 确保异常时也能重置状态
    local success, result = pcall(function()
        -- 根据订单类型选择不同的同步接口
        local url
        if task.data and task.data.deliveryOrderId then
            -- 发货订单使用 syncDeliveryOrder 接口
            url = string.format("%s/syncDeliveryOrder", baseUrl)
        else
            -- 收货订单使用 sync 接口
            url = string.format("%s/sync", baseUrl)
        end
        
        local ok = false
        if task.data then
            
            local queryParamsStr = HttpService:JSONEncode(task.data)
            log("flushQueue 订单同步数据: " .. tostring(queryParamsStr))
            local response = request({
                Url = url,
                Method = "POST",
                Headers = {
                    ["Content-Type"] = "application/json"
                },
                Body = HttpService:JSONEncode(task.data)
            })
            ok = response.Success
            local logData = {
                message = "flushQueue HTTP请求结果",
                taskId = task.id,
                success = ok,
                responseStatus = response.StatusCode,
                responseBody = response.Body
            }
            
            if task.data and task.data.deliveryOrderId then
                logData.deliveryOrderId = task.data.deliveryOrderId
            else
                logData.orderMainId = task.data.orderMainId
            end
            
            log(HttpService:JSONEncode(logData))

        else
            log(HttpService:JSONEncode({
                message = "flushQueue 任务数据为空",
                taskId = task.id
            }))
        end

        if ok then
            -- 请求成功，从队列中移除
            table.remove(syncState.queue, 1)

            log(HttpService:JSONEncode({
                message = "有序同步成功",
                taskId = task.id,
                recoveryMode = syncState.recoveryMode
            }))

            if task.data and task.deleteFriendInfo and task.deleteFriendInfo.robloxUserId then
                local isDeliveryOrder = task.data.deliveryOrderId ~= nil
                local orderStatus = task.data.orderStatus
                local makeStatus = task.data.makeStatus
                
                -- 统一处理发货订单(makeStatus=2或orderStatus=2)和收货订单(orderStatus=4)的完成状态
                if (isDeliveryOrder and makeStatus == 2) or (not isDeliveryOrder and orderStatus == 4) then
                    log(HttpService:JSONEncode({
                        message = "订单同步成功，开始删除好友",
                        taskId = task.id,
                        robloxUserId = task.deleteFriendInfo.robloxUserId,
                        receiveStatus = task.data.receiveStatus,
                        recoveryMode = syncState.recoveryMode
                    }))
                    
                    -- 检查用户ID是否在例外列表中
                    local shouldDelete = true
                    for _, exemptId in ipairs(EXEMPT_FRIEND_DELETE_USER_IDS) do
                        if task.deleteFriendInfo.robloxUserId == exemptId then
                            shouldDelete = false
                            break
                        end
                    end
                    
                    if shouldDelete then
                        deleteFriend(task.deleteFriendInfo.robloxUserId)
                    end
                end
            end

            -- 如果是订单完成：写入持久完成标记（acks_done）
            if task.data then
                local isDeliveryOrder = task.data.deliveryOrderId ~= nil
                local oid = nil
                
                if isDeliveryOrder then
                    -- 发货订单：检查 makeStatus == 2 和 deliveryOrderId
                    if task.data.makeStatus == 2 and task.data.deliveryOrderId then
                        oid = tostring(task.data.deliveryOrderId)
                    end
                else
                    -- 收货订单：检查 orderStatus == 4 和 orderMainId
                    if task.data.orderStatus == 4 and task.data.orderMainId then
                        oid = tostring(task.data.orderMainId)
                    end
                end
                
                if oid then
                    syncState.acks_done[oid] = os.time()
                end
            end

            -- 清理过期的完成标记
            local nowTs = os.time()
            -- 新表：acks_done 超过24小时清理
            for k, v in pairs(syncState.acks_done) do
                if nowTs - (v or 0) > 86400 then
                    syncState.acks_done[k] = nil
                end
            end
            
            -- 立即保存状态（移除已完成的记录）
            saveState()
        else
            -- 请求失败，增加重试次数并设置下次重试时间
            task.retry = (task.retry or 0) + 1
            task.nextAttemptAt = now + getRetryInterval(task.retry)

            log(HttpService:JSONEncode({
                message = "有序同步失败，等待重试",
                taskId = task.id,
                retry = task.retry,
                nextAttemptAt = task.nextAttemptAt
            }))

            saveState()
        end
    end)
    
    -- 无论成功还是失败，都要重置处理状态
    syncState.isProcessing = false
    saveState()  -- 立即保存状态重置，防止脚本重启后阻塞
    
    -- 如果出现异常，记录错误
    if not success then
        log(HttpService:JSONEncode({
            message = "flushQueue 处理异常",
            taskId = task.id,
            error = tostring(result)
        }))
    end
end

-- 将HTTP请求添加到可靠队列中
local function guaranteeSync(id, data, deleteFriendInfo)
    -- 判断是否为发货订单
    local isDeliveryOrder = data and data.deliveryOrderId ~= nil
    
    -- 若订单已被确认完成（acks_done），避免重复入队
    if data and syncState.acks_done then
        local oid = nil
        local orderIdField = nil
        
        if isDeliveryOrder then
            -- 发货订单：检查 makeStatus == 2 和 deliveryOrderId
            if data.makeStatus == 2 and data.deliveryOrderId then
                oid = tostring(data.deliveryOrderId)
                orderIdField = "deliveryOrderId"
            end
        else
            -- 收货订单：检查 orderStatus == 4 和 orderMainId
            if data.orderStatus == 4 and data.orderMainId then
                oid = tostring(data.orderMainId)
                orderIdField = "orderMainId"
            end
        end
        
        if oid and syncState.acks_done[oid] then
            log(HttpService:JSONEncode({
                message = "订单已完成(acks_done)，跳过入队",
                [orderIdField] = data[orderIdField],
                taskId = id,
                doneAt = syncState.acks_done[oid]
            }))
            return true
        end
    end

    -- 检查是否已在队列中
    for _, task in ipairs(syncState.queue) do
        if task.id == id then
            local logData = {
                message = "任务已在队列中，跳过重复入队",
                taskId = id
            }
            
            if isDeliveryOrder then
                logData.deliveryOrderId = data and data.deliveryOrderId
            else
                logData.orderMainId = data and data.orderMainId
            end
            
            log(HttpService:JSONEncode(logData))
            return true
        end
    end

    -- 添加到队列
    table.insert(syncState.queue, {
        id = id,
        data = data,  -- POST请求的数据
        deleteFriendInfo = deleteFriendInfo,  -- 删除好友信息
        retry = 0,
        nextAttemptAt = 0,
        createdAt = os.time()
    })
    local logData = {
        message = "任务已入队，准备同步",
        taskId = id,
        queueSize = #syncState.queue
    }
    
    if isDeliveryOrder then
        logData.deliveryOrderId = data and data.deliveryOrderId
    else
        logData.orderMainId = data and data.orderMainId
    end
    
    log(HttpService:JSONEncode(logData))


    saveState()  -- 保存状态
    flushQueue() -- 立即尝试发送
    return true
end

-- ================= 前端故障恢复 =================

-- 保存进行中的订单信息
local function saveActiveOrder(orderId, orderData, isDelivery)
    local isDeliveryOrder = isDelivery == true
    
    syncState.activeOrder = {
        user = orderData.user,
        initialInventory = orderData.initialInventory,
        totalReceived = orderData.totalReceived,
        startTime = orderData.startTime,
        lastUpdateTime = os.time(),
        receiveStatus = orderData.receiveStatus or 0
    }
    
    if isDeliveryOrder then
        syncState.activeOrder.deliveryOrderId = orderId
        syncState.activeOrder.items = orderData.items
        syncState.activeOrder.makeStatus = orderData.makeStatus
    else
        syncState.activeOrder.orderMainId = orderId
        syncState.activeOrder.orderList = orderData.orderList
        syncState.activeOrder.orderStatus = orderData.orderStatus
    end
    
    saveState()
end

-- 移除已完成的订单
local function removeActiveOrder(orderId)
    if syncState.activeOrder and (syncState.activeOrder.orderMainId == orderId or syncState.activeOrder.deliveryOrderId == orderId) then
        syncState.activeOrder = nil
        saveState()
    end
end

-- 更新订单进度
local function updateActiveOrderProgress(orderId, totalReceived,robloxUserId, receiveStatus)
    if syncState.activeOrder and (syncState.activeOrder.orderMainId == orderId or syncState.activeOrder.deliveryOrderId == orderId) then
        syncState.activeOrder.totalReceived = totalReceived
        syncState.activeOrder.robloxUserId = robloxUserId
        syncState.activeOrder.lastUpdateTime = os.time()
        if receiveStatus ~= nil then
            syncState.activeOrder.receiveStatus = receiveStatus
        end
        saveState()
    end
end


-- 检查并恢复进行中的订单（最多1个）
local function checkAndRecoverActiveOrders()
    if syncState.activeOrder then
        local now = os.time()
        syncState.activeOrder.lastUpdateTime = now
        local isDeliveryOrder = syncState.activeOrder.deliveryOrderId ~= nil
        
        -- 构建日志数据
        local logData = {
            message = "发现可恢复的进行中订单",
            user = syncState.activeOrder.user,
            totalReceived = syncState.activeOrder.totalReceived,
            lastUpdateTime = syncState.activeOrder.lastUpdateTime
        }
        
        if isDeliveryOrder then
            logData.deliveryOrderId = syncState.activeOrder.deliveryOrderId
        else
            logData.orderMainId = syncState.activeOrder.orderMainId
        end
        
        log(HttpService:JSONEncode(logData))
        return syncState.activeOrder
    end
    
    return nil
end

-- 恢复订单并同步已收到的物品
local function recoverOrderAndSync(orderData)
    local isDeliveryOrder = orderData.deliveryOrderId ~= nil
    local orderId = isDeliveryOrder and orderData.deliveryOrderId or orderData.orderMainId
    local orderType = isDeliveryOrder and "deliveryOrderId" or "orderMainId"
    local user = orderData.user
    local totalReceived = orderData.totalReceived

    -- 统一的日志记录
    log(HttpService:JSONEncode({
        message = "恢复订单并同步已收到物品",
        [orderType] = orderId,
        user = user,
        totalReceived = totalReceived
    }), {
        log_type = "trade_error",
        [orderType] = orderId,
        orderStatus = isDeliveryOrder and nil or orderData.orderStatus,
        makeStatus = isDeliveryOrder and orderData.makeStatus or nil,
    })

    -- 构建查询参数
    local queryParams = {
        authSecret = authSecret
    }
    
    -- 根据订单类型设置ID字段和状态字段
    if isDeliveryOrder then
        queryParams.deliveryOrderId = orderId
        queryParams.makeStatus = orderData.makeStatus
    else
        queryParams.orderMainId = orderId
        queryParams.orderStatus = orderData.orderStatus
    end

    -- 添加订单列表数据
    if isDeliveryOrder then
        -- 发货订单：根据库存快照计算当前已发出进度，并直接以错误结束（makeStatus=2, receiveStatus=4）
        local invSnapshot = select(1, getInventorySnapshot())
        local totalDelivered = {}
        if type(orderData.items) == "table" then
            for _, it in ipairs(orderData.items) do
                local itemId = it.tradeId
                local targetQuantity = it.orderQuantity
                local initialCount = (orderData.initialInventory and orderData.initialInventory[itemId]) or 0
                local currentCount = getItemNumFromSnapshot(invSnapshot, itemId)
                local delivered = math.max(0, initialCount - currentCount)
                totalDelivered[itemId] = {
                    orderId = it.deliveryOrderItemId,
                    quantity = math.min(delivered, targetQuantity),
                    deliveryOrderItemId = it.deliveryOrderItemId
                }
            end
        end
        queryParams.items = buildDeliveryItemsFromTotalDelivered(totalDelivered, 2, 4)
        queryParams.makeStatus = 2
        queryParams.receiveStatus = 4
    else
        -- 收货订单使用orderList字段（仅在有进度数据时）
        if totalReceived then
            queryParams.orderList = buildOrderListFromTotalReceived(totalReceived, orderData.orderStatus, orderData.receiveStatus)
        end
    end

    -- 生成同步ID
    local syncId = tostring(orderId) .. ":recovery"
    
    -- 如果是订单结束，传递删除好友信息
    local deleteFriendInfo = nil
    if ((isDeliveryOrder and queryParams.makeStatus == 2) or (not isDeliveryOrder and queryParams.orderStatus == 4)) and orderData.robloxUserId then
        deleteFriendInfo = {
            robloxUserId = orderData.robloxUserId
        }
    end

    guaranteeSync(syncId, queryParams, deleteFriendInfo)

    -- 若恢复时已判断完成或收货完成，立即移除活跃订单
    if (isDeliveryOrder and queryParams.makeStatus == 2) or (not isDeliveryOrder and queryParams.orderStatus == 4) then
        removeActiveOrder(orderId)
    end
end


-- 初始化状态
syncState = loadState()

-- 系统启动时的故障恢复检查
task.spawn(function()
    log(HttpService:JSONEncode({
        message = "开始系统启动时的故障恢复检查"
    }))

    -- 检查并恢复进行中的订单（最多1个）
    local orderToRecover = checkAndRecoverActiveOrders()

    if orderToRecover then
        local isDeliveryOrder = orderToRecover.deliveryOrderId ~= nil
        local orderId = isDeliveryOrder and orderToRecover.deliveryOrderId or orderToRecover.orderMainId
        local orderType = isDeliveryOrder and "deliveryOrderId" or "orderMainId"
        
        log(HttpService:JSONEncode({
            message = "发现需要恢复的订单",
            [orderType] = orderId,
            user = orderToRecover.user
        }))
    
        -- 恢复订单并同步已收到的物品
        recoverOrderAndSync(orderToRecover)
        
        log(HttpService:JSONEncode({
            message = "故障恢复检查完成",
            [orderType] = orderId
        }))

    else
        log(HttpService:JSONEncode({
            message = "未发现需要恢复的订单"
        }))
    end
end)

-- 后台处理循环
task.spawn(function()
    while true do
        flushQueue()

        -- 强制处理机制：如果队列不为空且长时间未处理，强制重置状态
        if #syncState.queue > 0 and syncState.isProcessing then
            local now = os.time()
            if syncState.lastProcessTime > 0 and (now - syncState.lastProcessTime) > 120 then -- 2分钟强制重置
                log(HttpService:JSONEncode({
                    message = "强制重置处理状态，队列可能被阻塞",
                    queueSize = #syncState.queue,
                    lastProcessTime = syncState.lastProcessTime,
                    timeSinceLastProcess = now - syncState.lastProcessTime
                }))
                syncState.isProcessing = false
                saveState()
            end
        end

        -- 动态调整等待时间
        local waitTime = SYNC_CONFIG.checkInterval

        if syncState.recoveryMode then
            waitTime = 2                                               -- 恢复模式：2秒
        elseif not syncState.serverHealthy then
            waitTime = math.min(30, 5 * syncState.consecutiveFailures) -- 故障模式：最长30秒
        end

        task.wait(waitTime)
    end
end)

-- ================ 原订单回调：改为入队保证送达 ================
local function reportOrder(data)
    local orderStatus, receiveStatus, orderMainId = data.orderStatus, data.receiveStatus, data.orderMainId
    local makeStatus = data.makeStatus  -- 发货订单使用makeStatus
    -- orderStatus 1 发货开始 2发货结束 (收货订单: 2开始 4结束)
    -- receiveStatus 1 成功 2 卖家未进私服 3 交易超时/不匹配/未确认 4 其它错误（程序异常/恢复模式上报）
    
    -- 判断是否为发货订单（通过检查是否有deliveryOrderId字段）
    local isDeliveryOrder = data.deliveryOrderId ~= nil
    
    -- 构建POST请求数据
    local queryParams = {
        authSecret = authSecret
    }
    
    -- 如果是发货订单，使用发货订单的字段名
    if isDeliveryOrder then
        queryParams.deliveryOrderId = data.deliveryOrderId
        -- 发货订单使用makeStatus字段
        queryParams.makeStatus = makeStatus or orderStatus
    else
        -- 收货订单使用原有字段：orderStatus 2(开始收货), 4(收货完成)
        queryParams.orderMainId = orderMainId
        queryParams.orderStatus = orderStatus
    end
    
    if orderStatus == 4 then
        -- queryParams.receiveStatus = receiveStatus
    end
    
    if data.totalReceived then
        queryParams.orderList = buildOrderListFromTotalReceived(data.totalReceived, orderStatus, receiveStatus)
    end
    
    -- 如果是发货订单且有totalDelivered数据，转换为发货订单格式
    if isDeliveryOrder and data.totalDelivered then
        queryParams.items = buildDeliveryItemsFromTotalDelivered(data.totalDelivered, orderStatus, receiveStatus)
    end
    
    local queryParamsStr = HttpService:JSONEncode(queryParams)
    log("回调 queryParamsStr: " .. tostring(queryParamsStr))

    if runTag ~= 0 then
        -- 将同步任务写入本地可靠队列，后台会自动重试直到成功
        -- 根据订单类型生成唯一任务ID：
        -- 收货：orderMainId:orderStatus:receiveStatus
        -- 发货：deliveryOrderId:makeStatus:receiveStatus
        local gid
        if isDeliveryOrder then
            gid = tostring(data.deliveryOrderId) .. ":" .. tostring(makeStatus or 0) .. ":" .. tostring(receiveStatus or 0)
        else
            gid = tostring(orderMainId) .. ":" .. tostring(orderStatus) .. ":" .. tostring(receiveStatus or 0)
        end
        
        -- 如果是订单结束，传递删除好友信息
        local deleteFriendInfo = nil
        if (isDeliveryOrder and (makeStatus == 2)) or (not isDeliveryOrder and orderStatus == 4) then
            if data.robloxUserId then
                deleteFriendInfo = {
                    robloxUserId = data.robloxUserId
                }
            end
        end        

        guaranteeSync(gid, queryParams, deleteFriendInfo)
    end
end

-- 核心：收货流程 - 支持多个物品
local function runReceiving(mainOrderData)
    local success, response = pcall(function()
        local user = mainOrderData.robloxUserName
        local orderMainId = mainOrderData.orderMainId
        local orderList = mainOrderData.orderList

        -- 记录初始库存数量
        local initialInventory = {}
        for _, order in ipairs(orderList) do
            local itemId = order.product.tradeId
            initialInventory[itemId] = getItemNum(itemId)
        end

        -- 回调"订单开始"
        local reportData = {
            orderMainId = orderMainId,
            orderStatus = 2
        }
        log(HttpService:JSONEncode({
            message = "收货开始交易",
            orderMainId = orderMainId,
            user = user,
            orderList = orderList,
            initialInventory = initialInventory
        }), {
            log_type = "trade_start",
            orderMainId = orderMainId,
            orderStatus = reportData.orderStatus
        })
        -- say("收货开始交易")
        sendTradeHint(6)
        reportOrder(reportData)

        -- 开始多轮交易，直到所有物品都收到
        local totalReceived = {}
        -- 初始化 totalReceived，包含 orderProductId 信息
        for _, order in ipairs(orderList) do
            local itemId = order.product.tradeId
            local orderProductId = order.product.orderProductId
            totalReceived[itemId] = {
                orderId = order.orderId,
                quantity = 0,
                orderProductId = orderProductId
            }
        end
        local startTime = os.time()
        local tradeRequestStartTime = os.time() -- 交易请求开始时间

        -- 保存进行中的订单信息到持久化存储
        local orderData = {
            user = user,
            orderList = orderList,
            initialInventory = initialInventory,
            totalReceived = totalReceived,
            startTime = startTime,
            orderStatus = reportData.orderStatus
        }
        saveActiveOrder(orderMainId, orderData, false)

        -- 检查是否为单物品订单（用于优化处理）
        local isSingleItemOrder = #orderList == 1
        local singleItemId = isSingleItemOrder and orderList[1].product.tradeId or nil
        local singleItemTargetQuantity = isSingleItemOrder and orderList[1].product.quantity or 0

        while true do
            -- 检查是否超时
            if os.time() - startTime > maxTradeTime then
                log(HttpService:JSONEncode({
                    message = "收货交易超时",
                    orderMainId = orderMainId,
                    user = user,
                    totalReceived = totalReceived
                }), {
                    log_type = "trade_error",
                    orderMainId = orderMainId,
                    orderStatus = 4,
                    receiveStatus = 3
                })

                -- 回调超时状态
                reportData.orderStatus = 4
                reportData.receiveStatus = 3
                reportData.totalReceived = totalReceived
                reportData.robloxUserId = mainOrderData.robloxUserId  -- 传递删除好友所需的用户ID
                reportOrder(reportData)
                -- 提示5：超过10分钟仍未完成
                sendTradeHint(5)
                -- 移除已完成的订单，避免重复处理
                removeActiveOrder(orderMainId)
                break
            end

            -- 检查是否所有物品都已收到（单次批量拉取库存快照）
            local invSnapshot = select(1, getInventorySnapshot())
            local allCompleted = true
            local progressInfo = {}

            for _, order in ipairs(orderList) do
                local itemId = order.product.tradeId
                local targetQuantity = order.product.quantity
                local currentQuantity = getItemNumFromSnapshot(invSnapshot, itemId)
                local receivedQuantity = totalReceived[itemId] and totalReceived[itemId].quantity or 0
                local actualReceived = currentQuantity - initialInventory[itemId]

                local progress = {
                    itemId = itemId,                                         -- 物品ID
                    targetQuantity = targetQuantity,                         -- 目标数量
                    currentQuantity = currentQuantity,                       -- 当前库存数量
                    receivedQuantity = receivedQuantity,                     -- 已收到数量
                    actualReceived = actualReceived,                         -- 实际收到数量
                    remaining = math.max(0, targetQuantity - actualReceived) -- 剩余需要数量
                }

                table.insert(progressInfo, progress)
                if actualReceived < targetQuantity then
                    allCompleted = false
                end
            end

            -- 每轮检查都记录进度
            if not allCompleted then
                log(HttpService:JSONEncode({
                    message = "收货交易进度",
                    orderMainId = orderMainId,
                    user = user,
                    progress = progressInfo,
                    totalReceived = totalReceived
                }), {
                    log_type = "progress",
                    orderMainId = orderMainId,
                    orderStatus = reportData.orderStatus
                })

                -- 更新持久化存储中的订单进度
                updateActiveOrderProgress(orderMainId, totalReceived,mainOrderData.robloxUserId, reportData.receiveStatus)
            end

            if allCompleted then
                log(HttpService:JSONEncode({
                    message = "收货交易完成",
                    orderMainId = orderMainId,
                    user = user,
                    totalReceived = totalReceived
                }), {
                    log_type = "trade_success",
                    orderMainId = orderMainId,
                    orderStatus = 4
                })

                -- 移除已完成的订单
                removeActiveOrder(orderMainId)

                -- 回调成功状态
                reportData.orderStatus = 4
                reportData.receiveStatus = 1
                reportData.totalReceived = totalReceived
                reportData.robloxUserId = mainOrderData.robloxUserId  -- 传递删除好友所需的用户ID
                reportOrder(reportData)
                break
            end

            -- 检查用户是否仍然在线且已准备就绪
            local isReady, reason = isUserOnlineAndReady(user)
            if not isReady then
                log(HttpService:JSONEncode({
                    message = "收货用户状态异常: " .. reason,
                    orderMainId = orderMainId,
                    user = user,
                    totalReceived = totalReceived,
                    reason = reason
                }), {
                    log_type = "trade_error",
                    orderMainId = orderMainId,
                    orderStatus = 4,
                    receiveStatus = 2
                })

                -- 回调用户掉线状态
                reportData.orderStatus = 4
                reportData.receiveStatus = 2
                reportData.totalReceived = totalReceived
                reportData.robloxUserId = mainOrderData.robloxUserId  -- 传递删除好友所需的用户ID
                reportOrder(reportData)

                -- 保留订单信息用于故障恢复，不删除
                break
            end

            -- 发起交易请求
            local curTradeStatus, tradeData = getCurTradeStatus()
            if curTradeStatus == "StartTrade" then
                Trade.DeclineTrade:FireServer()
                task.wait(0.5)
            end

            if curTradeStatus == "None" then
                local sendRes = sendTradeRequest(user)
                if not sendRes then
                    log(HttpService:JSONEncode({
                        message = "收货交易请求失败",
                        orderMainId = orderMainId,
                        user = user
                    }))
                    break
                end
            elseif curTradeStatus == "ReceivingRequest" then
                Trade.DeclineRequest:FireServer()
                task.wait(0.5)
                -- 视为对方发起但我方拒绝，后续若结束归类为 3
            end

            -- 等待交易状态变化
            local tradeStartTime = os.time()
            local tradeAccepted = false                                     -- 标记交易是否被接受
            local checkedMyOfferOnce = false                                 -- 仅在本轮首次进入 StartTrade 时自检我方交易栏

            while os.time() - tradeStartTime < singleTradeTimeoutSeconds do -- 单次交易最多等待1分钟
                local curTradeStatus, tradeData = getCurTradeStatus()

                if curTradeStatus == "StartTrade" and tradeData and tradeData.Player2 and tradeData.Player2.Accepted then
                    tradeAccepted = true -- 标记交易被接受
                    -- 收货侧：仅在本轮首次进入 StartTrade 时检查我方交易栏是否为空
                    if not checkedMyOfferOnce then
                        checkedMyOfferOnce = true
                        local myOfferCount = 0
                        if tradeData and tradeData.Player1 and type(tradeData.Player1.Offer) == "table" then
                            myOfferCount = #tradeData.Player1.Offer
                        end
                        if myOfferCount > 0 then
                            log(HttpService:JSONEncode({
                                message = "收货端：我方交易栏非空，取消本轮交易",
                                orderMainId = orderMainId,
                                user = user,
                                myOfferCount = myOfferCount
                            }), {
                                log_type = "trade_error",
                                orderMainId = orderMainId
                            })
                            Trade.DeclineTrade:FireServer()
                            task.wait(1)
                            break
                        end
                    end
                    -- 检查对方Offer的物品
                    local validItems = {}
                    local invalidItems = {}
                    local totalValidQuantity = 0

                    if tradeData.Player2.Offer then
                        for _, item in ipairs(tradeData.Player2.Offer) do
                            local itemId = item[1]
                            local itemQuantity = item[2] or 1

                            -- 检查是否在订单中
                            local isInOrder = false
                            for _, order in ipairs(orderList) do
                                if order.product.tradeId == itemId then
                                    local targetQuantity = order.product.quantity
                                    local currentReceived = totalReceived[itemId] and totalReceived[itemId].quantity or 0
                                    local currentInventory = getItemNum(itemId)
                                    local initialCount = initialInventory[itemId] or 0
                                    local actualReceived = currentInventory - initialCount

                                    -- 检查数量是否超过订单需求
                                    if actualReceived + itemQuantity <= targetQuantity then
                                        table.insert(validItems, { itemId = itemId, quantity = itemQuantity })
                                        totalValidQuantity = totalValidQuantity + itemQuantity
                                        isInOrder = true
                                        break
                                    else
                                        -- 数量超过需求，记录为无效
                                        local excessQuantity = (actualReceived + itemQuantity) - targetQuantity
                                        table.insert(invalidItems, {
                                            itemId = itemId,
                                            quantity = itemQuantity,
                                            reason = "数量超过订单需求",
                                            excessQuantity = excessQuantity
                                        })
                                    end
                                end
                            end

                            if not isInOrder then
                                table.insert(invalidItems, { itemId = itemId, quantity = itemQuantity, reason = "不在订单中" })
                            end
                        end
                    end

                    -- 如果有无效物品，拒绝交易
                    if #invalidItems > 0 then
                        log(HttpService:JSONEncode({
                            message = "收货交易包含无效物品，拒绝交易",
                            orderMainId = orderMainId,
                            user = user,
                            invalidItems = invalidItems,
                            validItems = validItems,
                            totalValidQuantity = totalValidQuantity
                        }), {
                            log_type = "trade_error",
                            orderMainId = orderMainId,
                        })

                        -- 拒绝交易并记录详细原因
                        Trade.DeclineTrade:FireServer()
                        task.wait(1)
                        -- 提示2/3：放错或过量（根据是否超过需求）
                        sendTradeHint(2)
                        

                        -- 记录拒绝原因，便于客服告知用户
                        local rejectReasons = {}
                        for _, item in ipairs(invalidItems) do
                            table.insert(rejectReasons, string.format("物品 %s x%d: %s",
                                item.itemId, item.quantity, item.reason))
                        end

                        log(HttpService:JSONEncode({
                            message = "交易被拒绝，原因如下",
                            orderMainId = orderMainId,
                            user = user,
                            rejectReasons = rejectReasons
                        }))
                        break
                    end

                    -- 如果都是有效物品，接受交易
                    if #validItems > 0 then
                        log(HttpService:JSONEncode({
                            message = "收货交易物品有效，接受交易",
                            orderMainId = orderMainId,
                            user = user,
                            validItems = validItems,
                            totalValidQuantity = totalValidQuantity
                        }), {
                            log_type = "progress",
                            orderMainId = orderMainId,
                            orderStatus = reportData.orderStatus
                        })
                        local acceptArgs = { [1] = game_id, [2] = tradeData.LastOffer }
                        Trade.AcceptTrade:FireServer(unpack(acceptArgs))
                        task.wait(2)
                        -- 接受后刷新库存再统计（单次批量拉取）
                        invSnapshot = select(1, getInventorySnapshot())

                        -- 更新已收到物品数量
                        for _, item in ipairs(validItems) do
                            if totalReceived[item.itemId] then
                                totalReceived[item.itemId].quantity = totalReceived[item.itemId].quantity + item.quantity
                            end
                        end

                        -- 更新持久化存储中的订单进度
                        updateActiveOrderProgress(orderMainId, totalReceived,mainOrderData.robloxUserId, reportData.receiveStatus)

                        log(HttpService:JSONEncode({
                            message = "收货交易成功，更新数量",
                            orderMainId = orderMainId,
                            user = user,
                            totalReceived = totalReceived,
                            thisTradeItems = validItems
                        }), {
                            log_type = "progress",
                            orderMainId = orderMainId,
                            orderStatus = reportData.orderStatus
                        })

                        -- 交易成功，重置交易请求开始时间
                        tradeRequestStartTime = os.time()

                        -- 单物品订单优化：如果交易数量满足需求，直接结束订单
                        if isSingleItemOrder and singleItemId then
                            -- 单物品直接结束判定前刷新库存（单次批量拉取）
                            invSnapshot = select(1, getInventorySnapshot())
                            local currentInventory = getItemNumFromSnapshot(invSnapshot, singleItemId)
                            local initialCount = initialInventory[singleItemId] or 0
                            local actualReceived = currentInventory - initialCount

                            if actualReceived <= singleItemTargetQuantity then
                                log(HttpService:JSONEncode({
                                    message = "单物品订单交易完成，直接结束订单",
                                    orderMainId = orderMainId,
                                    user = user,
                                    itemId = singleItemId,
                                    targetQuantity = singleItemTargetQuantity,
                                    actualReceived = actualReceived,
                                    totalReceived = totalReceived
                                }), {
                                    log_type = "trade_success",
                                    orderMainId = orderMainId,
                                    orderStatus = 4
                                })

                                -- 移除已完成的订单
                                removeActiveOrder(orderMainId)

                                -- 回调成功状态
                                reportData.orderStatus = 4
                                reportData.receiveStatus = 1
                                reportData.totalReceived = totalReceived
                                reportData.robloxUserId = mainOrderData.robloxUserId  -- 传递删除好友所需的用户ID
                                reportOrder(reportData)
                                return -- 直接结束整个收货流程
                            end
                        end

                        break
                    end
                end

                task.wait(2)
            end

            -- 检查交易是否被接受
            if not tradeAccepted then
                -- 统一调用：单轮1分钟结束取消未被同意的请求
                cancelPendingTradeRequest("收货端", orderMainId, user)
                
                local currentTime = os.time()
                local elapsedTime = currentTime - tradeRequestStartTime

                -- 如果交易请求累计等待超过x分钟，结束订单
                if elapsedTime >= maxTradeRequestTime then
                    local curTradeStatus, _ = getCurTradeStatus()
                    if curTradeStatus == "SendingRequest" then
                        Trade.CancelRequest:FireServer()
                    end
                    task.wait(1)
                    log(HttpService:JSONEncode({
                        message = "取消交易，交易请求对方无响应",
                        orderMainId = orderMainId,
                        user = user,
                        elapsedTime = elapsedTime,
                        maxTime = maxTradeRequestTime
                    }), {
                        log_type = "trade_error",
                        orderMainId = orderMainId,
                        orderStatus = 4,
                        receiveStatus = 3
                    })

                    reportData.orderStatus = 4
                    reportData.receiveStatus = 3
                    reportData.totalReceived = totalReceived
                    reportData.robloxUserId = mainOrderData.robloxUserId  -- 传递删除好友所需的用户ID
                    reportOrder(reportData)
                    -- 提示5：超时仍未完成
                    sendTradeHint(5)
                    -- 移除已完成的订单，避免重复处理
                    removeActiveOrder(orderMainId)
                    break
                end
            else
                -- 交易被接受，重置交易请求开始时间
                tradeRequestStartTime = os.time()
            end

            -- 交易完成后等待一段时间再发起下一轮
            task.wait(tradeInterval)
        end
    end)

    if not success then
        log("runReceiving err:" .. tostring(response))
        local reportData = {
            orderMainId = mainOrderData.orderMainId,
            orderStatus = 4,
            receiveStatus = 4, -- 程序异常
            robloxUserId = mainOrderData.robloxUserId  -- 传递删除好友所需的用户ID
        }
        reportOrder(reportData)
    end
end

-- 核心：发货流程 - 支持多个物品
local function runDelivery(mainOrderData)
    local success, response = pcall(function()
        local user = mainOrderData.robloxUserName
        local deliveryOrderId = mainOrderData.deliveryOrderId 
        local items = mainOrderData.items 

        -- 记录初始库存数量
        local initialInventory = {}
        for _, order in ipairs(items) do
            local itemId = order.tradeId 
            initialInventory[itemId] = getItemNum(itemId)
        end

        -- 回调"订单开始"
        local reportData = {
            deliveryOrderId = deliveryOrderId,  -- 发货订单使用deliveryOrderId
            makeStatus = 1
        }
        log(HttpService:JSONEncode({
            message = "发货开始交易",
            deliveryOrderId = deliveryOrderId,
            user = user,
            items = items,
            initialInventory = initialInventory
        }), {
            log_type = "trade_start",
            deliveryOrderId = deliveryOrderId,
            makeStatus = reportData.makeStatus
        })
        -- say("发货开始交易")
        sendTradeHint(7)
        reportOrder(reportData)

        -- 保存进行中的订单信息（用于故障恢复）
        local orderData = {
            deliveryOrderId = deliveryOrderId,
            user = user,
            items = items,
            initialInventory = initialInventory,
            startTime = os.time(),
            makeStatus = reportData.makeStatus
        }
        saveActiveOrder(deliveryOrderId, orderData, true)

        -- 检查用户是否在线且已准备就绪
        local isReady, reason = isUserOnlineAndReady(user)
        if not isReady then
            log(HttpService:JSONEncode({
                message = "发货用户状态异常: " .. reason,
                deliveryOrderId = deliveryOrderId,
                user = user,
                reason = reason
            }), {
                log_type = "trade_error",
                deliveryOrderId = deliveryOrderId,
                makeStatus = 2,
                receiveStatus = 2
            })

            -- 回调用户掉线状态
            reportData.makeStatus = 2
            reportData.receiveStatus = 2
            reportData.robloxUserId = mainOrderData.robloxUserId  -- 传递删除好友所需的用户ID
            reportOrder(reportData)
            
            return
        end

        -- 检查所有物品库存是否充足
        local inventoryCheck = {}
        local allItemsAvailable = true
        for _, order in ipairs(items) do
            local itemId = order.tradeId
            local targetQuantity = order.orderQuantity
            local currentQuantity = getItemNum(itemId)

            local check = {
                itemId = itemId,
                targetQuantity = targetQuantity,
                currentQuantity = currentQuantity,
                available = currentQuantity >= targetQuantity
            }
            table.insert(inventoryCheck, check)

            if not check.available then
                allItemsAvailable = false
            end
        end

        if not allItemsAvailable then
            log(HttpService:JSONEncode({
                message = "发货库存不足",
                deliveryOrderId = deliveryOrderId,
                user = user,
                inventoryCheck = inventoryCheck
            }), {
                log_type = "trade_error",
                deliveryOrderId = deliveryOrderId,
                makeStatus = 2,
                receiveStatus = 4
            })

            -- 回调库存不足状态
            reportData.makeStatus = 2
            reportData.receiveStatus = 4
            reportData.robloxUserId = mainOrderData.robloxUserId  -- 传递删除好友所需的用户ID
            reportOrder(reportData)
            
            -- 移除已完成的订单，避免重复处理
            removeActiveOrder(deliveryOrderId)
            
            -- 不直接return，让系统继续处理其他订单
            log(HttpService:JSONEncode({
                message = "发货库存不足，订单已取消，继续处理其他订单",
                deliveryOrderId = deliveryOrderId,
                user = user
            }))
            -- say("库存不足，订单已取消")
            say("Insufficient inventory, order canceled")
            return
        end

        -- 开始多轮交易，直到所有物品都发出
        local totalDelivered = {}
        -- 初始化 totalDelivered
        for _, order in ipairs(items) do
            local itemId = order.tradeId
            local deliveryOrderItemId = order.deliveryOrderItemId  -- 使用deliveryOrderItemId作为orderProductId
            totalDelivered[itemId] = {
                orderId = order.orderId or order.deliveryOrderItemId,  -- 兼容新旧格式
                quantity = 0,
                deliveryOrderItemId = deliveryOrderItemId
            }
        end
        local startTime = os.time()
        local tradeRequestStartTime = os.time() -- 交易请求开始时间

        while true do
            -- 检查是否超时
            if os.time() - startTime > maxTradeTime then
                log(HttpService:JSONEncode({
                    message = "发货交易超时",
                    deliveryOrderId = deliveryOrderId,
                    user = user,
                    totalDelivered = totalDelivered
                }), {
                    log_type = "trade_error",
                    deliveryOrderId = deliveryOrderId,
                    makeStatus = 2,
                    receiveStatus = 3
                })

                -- 回调超时状态
                reportData.makeStatus = 2
                reportData.receiveStatus = 3
                reportData.totalDelivered = totalDelivered
                reportData.robloxUserId = mainOrderData.robloxUserId  -- 传递删除好友所需的用户ID
                reportOrder(reportData)
                
                -- 移除已完成的订单，避免重复处理
                removeActiveOrder(deliveryOrderId)
                -- 提示5：超过10分钟仍未完成
                sendTradeHint(5)
                break
            end

            -- 检查是否所有物品都已发出（单次批量拉取库存快照，避免多次RPC）
            local invSnapshot = select(1, getInventorySnapshot())
            local allCompleted = true
            local progressInfo = {}

            for _, order in ipairs(items) do
                local itemId = order.tradeId 
                local targetQuantity = order.orderQuantity
                local currentQuantity = getItemNumFromSnapshot(invSnapshot, itemId)
                local deliveredQuantity = totalDelivered[itemId] and totalDelivered[itemId].quantity or 0
                local actualDelivered = initialInventory[itemId] - currentQuantity

                local progress = {
                    itemId = itemId,                                          -- 物品ID
                    targetQuantity = targetQuantity,                          -- 目标数量
                    currentQuantity = currentQuantity,                        -- 当前库存数量
                    deliveredQuantity = deliveredQuantity,                    -- 已发出数量
                    actualDelivered = actualDelivered,                        -- 实际发出数量
                    remaining = math.max(0, targetQuantity - actualDelivered) -- 剩余需要数量
                }

                table.insert(progressInfo, progress)
                if actualDelivered < targetQuantity then
                    allCompleted = false
                end
            end

            -- 每轮检查都记录进度
            if not allCompleted then
                log(HttpService:JSONEncode({
                    message = "发货交易进度",
                    deliveryOrderId = deliveryOrderId,
                    user = user,
                    progress = progressInfo,
                    totalDelivered = totalDelivered
                }), {
                    log_type = "progress",
                    deliveryOrderId = deliveryOrderId,
                    makeStatus = reportData.makeStatus
                })
            end

            if allCompleted then
                log(HttpService:JSONEncode({
                    message = "发货交易完成",
                    deliveryOrderId = deliveryOrderId,
                    user = user,
                    totalDelivered = totalDelivered
                }), {
                    log_type = "trade_success",
                    deliveryOrderId = deliveryOrderId,
                    makeStatus = 2
                })

                -- 回调成功状态
                reportData.makeStatus = 2
                reportData.receiveStatus = 1
                reportData.totalDelivered = totalDelivered
                reportData.robloxUserId = mainOrderData.robloxUserId  -- 传递删除好友所需的用户ID
                reportOrder(reportData)
                
                -- 移除已完成的订单，避免重复处理
                removeActiveOrder(deliveryOrderId)
                break
            end

            -- 检查用户是否仍然在线且已准备就绪
            local isReady, reason = isUserOnlineAndReady(user)
            if not isReady then
                log(HttpService:JSONEncode({
                    message = "发货用户状态异常: " .. reason,
                    deliveryOrderId = deliveryOrderId,
                    user = user,
                    totalDelivered = totalDelivered,
                    reason = reason
                }), {
                    log_type = "trade_error",
                    deliveryOrderId = deliveryOrderId,
                    makeStatus = 2,
                    receiveStatus = 2
                })

                -- 回调用户掉线状态
                reportData.makeStatus = 2
                reportData.receiveStatus = 2
                reportData.totalDelivered = totalDelivered
                reportData.robloxUserId = mainOrderData.robloxUserId  -- 传递删除好友所需的用户ID
                reportOrder(reportData)
                
                
                -- 移除已完成的订单，避免重复处理
                removeActiveOrder(deliveryOrderId)
                break
            end

            -- 发起交易请求
            local curTradeStatus, tradeData = getCurTradeStatus()
            if curTradeStatus == "StartTrade" then
                Trade.DeclineTrade:FireServer()
                task.wait(0.5)
            end

            if curTradeStatus == "None" then
                local sendRes = sendTradeRequest(user)
                if not sendRes then
                    log(HttpService:JSONEncode({
                        message = "发货交易请求失败",
                        deliveryOrderId = deliveryOrderId,
                        user = user
                    }))
                    break
                end
            elseif curTradeStatus == "ReceivingRequest" then
                Trade.DeclineRequest:FireServer()
                task.wait(0.5)
            end

            -- 等待交易状态变化
            local tradeStartTime = os.time()
            local tradeAccepted = false                                     -- 标记交易是否被接受

            while os.time() - tradeStartTime < singleTradeTimeoutSeconds do -- 单次交易最多等待1分钟
                local curTradeStatus, tradeData = getCurTradeStatus()
                if curTradeStatus == "StartTrade" then
                    tradeAccepted = true -- 标记交易被接受

                    -- 计算本次需要发出的物品
                    local itemsToOffer = {}
                    for _, order in ipairs(items) do
                        local itemId = order.tradeId 
                        local targetQuantity = order.orderQuantity
                        local currentQuantity = getItemNum(itemId)
                        local actualDelivered = initialInventory[itemId] - currentQuantity
                        local remaining = math.max(0, targetQuantity - actualDelivered)
                        -- 找出没交交易完成的物品，放入itemsToOffer
                        if remaining > 0 then
                            table.insert(itemsToOffer, {
                                itemId = itemId,
                                quantity = remaining
                            })
                        end
                    end
                    log(string.format("发货 #itemsToOffer:%s", #itemsToOffer))
                    if #itemsToOffer > 0 then
                        log(HttpService:JSONEncode({
                            message = "发货交易准备物品",
                            deliveryOrderId = deliveryOrderId,
                            user = user,
                            itemsToOffer = itemsToOffer
                        }), {
                            log_type = "progress",
                            deliveryOrderId = deliveryOrderId,
                            makeStatus = reportData.makeStatus
                        })

                        -- 将物品放入交易框（优化版本，限制最多4个物品）
                        local actualItemsOffered = addItemsToTradeOptimized(itemsToOffer)

                        log(HttpService:JSONEncode({
                            message = "发货交易物品已放入交易框",
                            deliveryOrderId = deliveryOrderId,
                            user = user,
                            itemsToOffer = itemsToOffer,
                            actualItemsOffered = actualItemsOffered
                        }))

                        -- 等待对方接受且对方Offer为空（复用外层1分钟限制，不再单独用 maxWaitAccept）
                        local hasSentWrongItemsHint = false
                        while os.time() - tradeStartTime < singleTradeTimeoutSeconds do
                            local curTradeStatus, tradeData = getCurTradeStatus()
                            local peerAccepted = tradeData and tradeData.Player2 and tradeData.Player2.Accepted
                            local peerOfferCount = 0
                            if tradeData and tradeData.Player2 and type(tradeData.Player2.Offer) == "table" then
                                peerOfferCount = #tradeData.Player2.Offer
                            end

                            if peerOfferCount > 0 then
                                log(string.format("发货orderId:%s 对方Offer不为空(数量:%s)，等待其移除", deliveryOrderId, peerOfferCount))
                                if not hasSentWrongItemsHint then
                                    hasSentWrongItemsHint = true
                                    -- 提示3：请放置正确的物品（发货端要求对方不放物品）
                                    sendTradeHint(3)
                                end
                            end

                            if peerAccepted and peerOfferCount == 0 then
                                log("对方已接受且未放物品，准备接受交易")
                                break
                            end
                            task.wait(1)
                        end

                        -- 若已超出本轮时间预算，则跳出等待下一轮
                        if os.time() - tradeStartTime >= singleTradeTimeoutSeconds then
                            break
                        end

                        -- 接受交易
                        local curTradeStatus, tradeData = getCurTradeStatus()
                        -- log(string.format("tradeData:%s ", HttpService:JSONEncode(tradeData)))
                        local acceptArgs = { [1] = game_id, [2] = tradeData.LastOffer }
                        Trade.AcceptTrade:FireServer(unpack(acceptArgs))
                        -- log(string.format("发货orderId:%s user:%s 自己 AcceptTrade", deliveryOrderId, user))

                        -- 等待交易完成，等待服务端把交易状态从 StartTrade 落回 None，确保交易真正完成后再记账；去掉后会有这些风险
                        while os.time() - tradeStartTime < singleTradeTimeoutSeconds do
                            local curTradeStatus, _ = getCurTradeStatus()
                            if curTradeStatus == "None" then
                                -- 交易落回None后刷新库存再记账（单次批量拉取）
                                invSnapshot = select(1, getInventorySnapshot())
                                -- 更新已发出物品数量（使用实际放入的物品）
                                for _, item in ipairs(actualItemsOffered) do
                                    if totalDelivered[item.itemId] then
                                        totalDelivered[item.itemId].quantity = totalDelivered[item.itemId].quantity + item.quantity
                                    end
                                end

                                -- 更新发货订单进度
                                updateActiveOrderProgress(deliveryOrderId, totalDelivered, mainOrderData.robloxUserId, nil)

                                log(HttpService:JSONEncode({
                                    message = "发货交易成功，更新数量",
                                    deliveryOrderId = deliveryOrderId,
                                    user = user,
                                    totalDelivered = totalDelivered,
                                    thisTradeItems = actualItemsOffered,
                                    originalItemsToOffer = itemsToOffer
                                }), {
                                    log_type = "progress",
                                    deliveryOrderId = deliveryOrderId,
                                    makeStatus = reportData.makeStatus
                                })

                                -- 交易成功，重置交易请求开始时间
                                tradeRequestStartTime = os.time()

                                -- 发货不做单物品特殊处理，继续按轮次逻辑

                                break
                            end
                            task.wait(1)
                        end

                        if os.time() - tradeStartTime >= singleTradeTimeoutSeconds then
                            log(string.format("发货 orderId:%s user:%s 确认完成超时", deliveryOrderId, user))
                            reportData.makeStatus = 2
                            reportData.receiveStatus = 3
                            reportData.totalDelivered = totalDelivered
                            reportData.robloxUserId = mainOrderData.robloxUserId  -- 传递删除好友所需的用户ID
                            reportOrder(reportData)
                            -- 移除已完成的订单，避免重复处理
                            removeActiveOrder(deliveryOrderId)
                            return
                        end
                    end

                    break
                end

                task.wait(2)
            end

            -- 检查交易是否被接受
            if not tradeAccepted then
                -- 统一调用：单轮1分钟结束取消未被同意的请求（发货端）
                cancelPendingTradeRequest("发货端", deliveryOrderId, user)
                
                local currentTime = os.time()
                local elapsedTime = currentTime - tradeRequestStartTime

                -- 如果交易请求等待时间超过x分钟，结束订单
                if elapsedTime >= maxTradeRequestTime then
                    local curTradeStatus, _ = getCurTradeStatus()
                    if curTradeStatus == "SendingRequest" then
                        Trade.CancelRequest:FireServer()
                    end
                    task.wait(1)
                    log(HttpService:JSONEncode({
                        message = "取消交易，交易请求对方无响应",
                        deliveryOrderId = deliveryOrderId,
                        user = user,
                        elapsedTime = elapsedTime,
                        maxTime = maxTradeRequestTime
                    }), {
                        log_type = "trade_error",
                        deliveryOrderId = deliveryOrderId,
                        makeStatus = 2,
                        receiveStatus = 3
                    })

                    reportData.makeStatus = 2
                    reportData.receiveStatus = 3
                    reportData.totalDelivered = totalDelivered
                    reportOrder(reportData)
                    -- 提示5：超时仍未完成
                    sendTradeHint(5)
                    -- 移除已完成的订单，避免重复处理
                    removeActiveOrder(deliveryOrderId)
                    break
                end
            else
                -- 交易被接受，重置交易请求开始时间
                tradeRequestStartTime = os.time()
            end

            -- 交易完成后等待一段时间再发起下一轮
            task.wait(tradeInterval)
        end
    end)

    if not success then
        log("runDelivery err:" .. tostring(response))
        local reportData = {
            deliveryOrderId = mainOrderData.deliveryOrderId,
            makeStatus = 2,
            receiveStatus = 4, -- 程序异常
            robloxUserId = mainOrderData.robloxUserId  -- 传递删除好友所需的用户ID
        }
        reportOrder(reportData)
        
        -- 移除异常的订单，避免重复处理
        removeActiveOrder(mainOrderData.deliveryOrderId)
    end
end

local function run()
    while true do
        -- 同时获取收货和发货订单
        local ReceivingData = getReceivingOrder()
        local DeliveryData = getDeliveryOrder()
        
        -- 检查是否有订单数据
        local hasReceiving = ReceivingData and ReceivingData.orderMainId
        local hasDelivery = DeliveryData and DeliveryData.deliveryOrderId
        
        if hasReceiving or hasDelivery then
            -- 如果两个订单都存在，根据createTime决定先处理哪个
            local shouldProcessReceiving = false
            local shouldProcessDelivery = false
            
            if hasReceiving and hasDelivery then
                -- 比较createTime，时间小的先处理
                local receivingTime = ReceivingData.createTime or 0
                local deliveryTime = DeliveryData.createTime or 0
                
                local logData = {
                    receivingTime = receivingTime,
                    deliveryTime = deliveryTime
                }
                
                if receivingTime <= deliveryTime then
                    shouldProcessReceiving = true
                    logData.message = "收货订单时间更早，先处理收货"
                    logData.receivingOrderId = ReceivingData.orderMainId
                    logData.deliveryOrderId = DeliveryData.deliveryOrderId
                else
                    shouldProcessDelivery = true
                    logData.message = "发货订单时间更早，先处理发货"
                    logData.deliveryOrderId = DeliveryData.deliveryOrderId
                    logData.receivingOrderId = ReceivingData.orderMainId
                end
                
                -- log(HttpService:JSONEncode(logData))

                
            elseif hasReceiving then
                shouldProcessReceiving = true
            elseif hasDelivery then
                shouldProcessDelivery = true
            end
            
            -- 处理收货订单
            if shouldProcessReceiving then
                -- 检查订单是否已经在处理中或已完成，避免重复处理
                local orderMainId = ReceivingData.orderMainId
                if syncState.activeOrder and syncState.activeOrder.orderMainId == orderMainId then
                    -- log(HttpService:JSONEncode({
                    --     message = "收货订单正在处理中，跳过重复处理",
                    --     orderMainId = orderMainId,
                    --     user = ReceivingData.robloxUserName
                    -- }))
                elseif syncState.acks_done and syncState.acks_done[tostring(orderMainId)] then
                    -- log(HttpService:JSONEncode({
                    --     message = "收货订单已完成，跳过重复处理",
                    --     orderMainId = orderMainId,
                    --     user = ReceivingData.robloxUserName,
                    --     doneAt = syncState.acks_done[tostring(orderMainId)]
                    -- }))
                else
                    -- 先判断玩家是否在线且在同一房间；不在线则最多等待10分钟，期间轮询
                    local user = ReceivingData.robloxUserName
                    local onlineWaitStart = os.time()
                    local isInRoom, reason = isUserInSameRoom(user)
                    local didWaitForOnline = false
                    local hasLoggedWait = false -- 只打印一次等待日志
                    while not isInRoom and (os.time() - onlineWaitStart) < waitTradeTime do
                        task.wait(5)
                        isInRoom, reason = isUserInSameRoom(user)
                        didWaitForOnline = true

                        if not hasLoggedWait then
                            hasLoggedWait = true
                            log(HttpService:JSONEncode({
                                message = "等待收货玩家上线: " .. tostring(reason),
                                user = user,
                                waited = tostring(os.time() - onlineWaitStart),
                                reason = reason
                            }))
                        end
                    end

                    if isInRoom then
                        if didWaitForOnline then
                            -- 刚从离线转为在线：等待玩家完全加载后再开始收货交易
                            log(HttpService:JSONEncode({
                                message = "收货玩家刚上线，等待完全加载后发起交易",
                                user = user,
                                orderMainId = ReceivingData.orderMainId
                            }))

                            -- 等待玩家完全加载（最多等待30秒）
                            local isReady, reason = waitForUserReady(user, 30)
                            if not isReady then
                                log(HttpService:JSONEncode({
                                    message = "等待玩家加载超时: " .. reason,
                                    user = user,
                                    orderMainId = ReceivingData.orderMainId
                                }), { log_type = "trade_error", orderMainId = ReceivingData.orderMainId, orderStatus = 2 })
                            else
                                -- 额外缓冲30秒确保玩家完全稳定
                                task.wait(30)
                                -- 玩家刚上线，需要检查交易系统是否就绪（最多等待15秒）
                                local okTrade = waitTradeStatusReady(15)
                                if not okTrade then
                                    log(HttpService:JSONEncode({
                                        message = "交易系统未就绪，跳过本轮再试",
                                        user = user,
                                        orderMainId = ReceivingData.orderMainId
                                    }), { log_type = "trade_error", orderMainId = ReceivingData.orderMainId, orderStatus = 2 })
                                else
                                    runReceiving(ReceivingData)
                                end
                            end
                        else
                            -- 一开始就在线：确保玩家已准备就绪后直接发起交易
                            local isReady, reason = isUserOnlineAndReady(user)
                            if not isReady then
                                log(HttpService:JSONEncode({
                                    message = "玩家未准备就绪: " .. reason,
                                    user = user,
                                    orderMainId = ReceivingData.orderMainId
                                }), { log_type = "trade_error", orderMainId = ReceivingData.orderMainId, orderStatus = 2 })
                            else
                                log(HttpService:JSONEncode({
                                    message = "收货玩家已准备就绪，立即发起交易",
                                    user = user,
                                    orderMainId = ReceivingData.orderMainId
                                }))
                                -- 玩家一直在线，交易系统应该已经就绪，直接发起交易
                                runReceiving(ReceivingData)
                            end
                        end
                    else
                        local reportData = {
                            orderMainId = ReceivingData.orderMainId,
                            orderStatus = 2  -- 收货开始
                        }
                        reportOrder(reportData)

                        -- 超时仍未上线，回调 receiveStatus=2
                        log(HttpService:JSONEncode({
                            message = "收货玩家长时间不在线，跳过本轮订单",
                            user = user,
                            orderMainId = ReceivingData.orderMainId
                        }), {
                            log_type = "trade_error",
                            orderMainId = ReceivingData.orderMainId,
                            orderStatus = 4
                        })

                        reportOrder({
                            orderMainId = ReceivingData.orderMainId,
                            orderStatus = 4,
                            receiveStatus = 2,
                            robloxUserId = ReceivingData.robloxUserId  -- 传递删除好友所需的用户ID
                        })
                    end
                end  -- 添加这个 end 来关闭 else 块
            end
            
            -- 处理发货订单
            if shouldProcessDelivery then
                -- 检查订单是否已经在处理中或已完成，避免重复处理
                local deliveryOrderId = DeliveryData.deliveryOrderId
                if syncState.activeOrder and syncState.activeOrder.deliveryOrderId == deliveryOrderId then
                    -- log(HttpService:JSONEncode({
                    --     message = "发货订单正在处理中，跳过重复处理",
                    --     deliveryOrderId = deliveryOrderId,
                    --     user = DeliveryData.robloxUserName
                    -- }))
                elseif syncState.acks_done and syncState.acks_done[tostring(deliveryOrderId)] then
                    -- log(HttpService:JSONEncode({
                    --     message = "发货订单已完成，跳过重复处理",
                    --     deliveryOrderId = deliveryOrderId,
                    --     user = DeliveryData.robloxUserName,
                    --     doneAt = syncState.acks_done[tostring(deliveryOrderId)]
                    -- }))
                else
                    -- 先判断玩家是否在线且在同一房间；不在线则最多等待10分钟，期间轮询
                    local user = DeliveryData.robloxUserName
                    local onlineWaitStart = os.time()
                    local isInRoom, reason = isUserInSameRoom(user)
                    local didWaitForOnline = false
                    local hasLoggedWait = false -- 只打印一次等待日志
                    while not isInRoom and (os.time() - onlineWaitStart) < waitTradeTime do
                        task.wait(5)

                        isInRoom, reason = isUserInSameRoom(user)
                        didWaitForOnline = true

                        if not hasLoggedWait then
                            hasLoggedWait = true
                            log(HttpService:JSONEncode({
                                message = "等待发货玩家上线: " .. tostring(reason),
                                user = user,
                                waited = tostring(os.time() - onlineWaitStart),
                                reason = reason
                            }))
                        end
                    end

                    if isInRoom then
                        if didWaitForOnline then
                            -- 刚从离线转为在线：等待玩家完全加载后再开始发货交易
                            log(HttpService:JSONEncode({
                                message = "发货玩家刚上线，等待完全加载后发起交易",
                                user = user,
                                deliveryOrderId = DeliveryData.deliveryOrderId
                            }))

                            -- 等待玩家完全加载（最多等待30秒）
                            local isReady, reason = waitForUserReady(user, 30)
                            if not isReady then
                                log(HttpService:JSONEncode({
                                    message = "等待玩家加载超时: " .. reason,
                                    user = user,
                                    deliveryOrderId = DeliveryData.deliveryOrderId
                                }), { log_type = "trade_error", deliveryOrderId = DeliveryData.deliveryOrderId, makeStatus = 2 })
                            else
                                -- 额外缓冲30秒确保玩家完全稳定
                                task.wait(30)
                                -- 玩家刚上线，需要检查交易系统是否就绪（最多等待15秒）
                                local okTrade = waitTradeStatusReady(15)
                                if not okTrade then
                                    log(HttpService:JSONEncode({
                                        message = "交易系统未就绪，跳过本轮再试",
                                        user = user,
                                        deliveryOrderId = DeliveryData.deliveryOrderId
                                    }), { log_type = "trade_error", deliveryOrderId = DeliveryData.deliveryOrderId, makeStatus = 2 })
                                else
                                    runDelivery(DeliveryData)
                                end
                            end
                        else
                            -- 一开始就在线：确保玩家已准备就绪后直接发起交易
                            local isReady, reason = isUserOnlineAndReady(user)
                            if not isReady then
                                log(HttpService:JSONEncode({
                                    message = "玩家未准备就绪: " .. reason,
                                    user = user,
                                    deliveryOrderId = DeliveryData.deliveryOrderId
                                }), { log_type = "trade_error", deliveryOrderId = DeliveryData.deliveryOrderId, makeStatus = 2 })
                            else
                                log(HttpService:JSONEncode({
                                    message = "发货玩家已准备就绪，立即发起交易",
                                    user = user,
                                    deliveryOrderId = DeliveryData.deliveryOrderId
                                }))
                                -- 玩家一直在线，交易系统应该已经就绪，直接发起交易
                                runDelivery(DeliveryData)
                            end
                        end
                    else
                        
                        local reportData = {
                            deliveryOrderId = DeliveryData.deliveryOrderId,
                            makeStatus = 1  -- 发货开始
                        }
                        reportOrder(reportData)
                        -- 超时仍未上线，回调 receiveStatus=2
                        log(HttpService:JSONEncode({
                            message = "发货玩家长时间不在线，跳过本轮订单",
                            user = user,
                            deliveryOrderId = DeliveryData.deliveryOrderId
                        }), {
                            log_type = "trade_error",
                            deliveryOrderId = DeliveryData.deliveryOrderId,
                            makeStatus = 2
                        })

                        reportOrder({
                            deliveryOrderId = DeliveryData.deliveryOrderId,
                            makeStatus = 2,
                            receiveStatus = 2,
                            robloxUserId = DeliveryData.robloxUserId  -- 传递删除好友所需的用户ID
                        })
                    end
                end  -- 添加这个 end 来关闭 else 块
            end
        else
            -- 没有订单时，短暂等待后继续循环
            task.wait(postOrderWaitSeconds)
        end
        
    end
end

task.spawn(run)
